/*
 * Copyright 2014-2026 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.wzq.util;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.UUID;

/**
 */
public class UtilString {
	public static final int md5Len = md5("empty").length(), uuidLen = uuid().length();
	private static final Random random = new Random();
	private static final Set<String> chinaPhones = new HashSet<>();
	
	static {
		chinaPhones.addAll(Arrays.asList("134,135,136,137,138,139,150,151,152,157,158,159,147,182,183,184,187,188,178".split(",")));
		chinaPhones.addAll(Arrays.asList("130,131,132,155,156,185,186,176".split(",")));
		chinaPhones.addAll(Arrays.asList("133,153,180,181,189,177".split(",")));
	}
	
	
	private static String fetchDigit(String text, int start) {
		if (text == null) return "";
		
		StringBuilder buf = new StringBuilder();
		boolean begin = false;
		for (int len = text.length(); start < len; start++) {
			char ch = text.charAt(start);
			if (ch >= '0' && ch <= '9') {
				begin = true;
				buf.append(ch);
			} else if (begin) {
				break;
			}
		}
		return buf.toString();
	}
	public static Integer fetchInt(String text, int start) {
		String value = fetchDigit(text, start);
		return value.length() > 0 ? Integer.valueOf(value.toString()) : null;
	}
	public static Long fetchLong(String text, int start) {
		String value = fetchDigit(text, start);
		return value.length() > 0 ? Long.valueOf(value.toString()) : null;
	}
	/** Returns val represented by the specified number of hex digits. */
    private static String digits(long val, int digits) {
        long hi = 1L << (digits * 4);
        return Long.toHexString(hi | (val & (hi - 1))).substring(1);
    }
    /** uuid方法，结果中没有-符号，耗时只有replaceAll的30% */
	public static String uuid() {
		UUID uuid = UUID.randomUUID();
		long mostSigBits = uuid.getMostSignificantBits(), leastSigBits = uuid.getLeastSignificantBits();
		return digits(mostSigBits >> 32, 8)+ digits(mostSigBits >> 16, 4)
				+ digits(mostSigBits, 4) + digits(leastSigBits >> 48, 4) + digits(leastSigBits, 12);
        
	}
	
	/** 耗时只有{@linkplain java.math.BigInteger#toString(int) new BigInteger(bytes).toString(16)}的40% */
	public static String toHexString(byte[] bytes) {
    	StringBuilder buf = new StringBuilder(bytes.length * 2);
    	for (int i = 0, len = bytes.length, value; i < len; i++) {
    		value = bytes[i] & 0xff;
    		if (value < 0x10) buf.append('0');
			buf.append(Integer.toHexString(value));
		}
        return buf.toString();
	}
	
	/**
     * 将输入字符串经过MD5处理后返回
     * @param values 待处理字符串
     * @return MD5之后的结果
     */
    public static String md5(String... values) {
    	return md5(Arrays.asList(values));
    }
    /** 将输入字符串经过MD5处理后返回 */
    public static String md5(Collection<String> values) {
    	MessageDigest messageDigest = getMessageDigest("MD5");
    	for (String value : values) {
    		if (value != null) messageDigest.update(value.getBytes(UtilIo.utf8));
    	}
        return toHexString(messageDigest.digest());
    }
    /** @param algorithm 例如：MD5 */
    public static MessageDigest getMessageDigest(String algorithm) {
    	try {
			return MessageDigest.getInstance(algorithm.toUpperCase());
		} catch (NoSuchAlgorithmException e) {
			throw new IllegalStateException("MD5 provider not exist!");
    	}
    }

    public static boolean isChinaPhone(String phone) {
    	return phone != null && phone.length() == 11 && phone.charAt(0) == '1' && chinaPhones.contains(phone.substring(0, 3));
    }
	
    public static boolean isEmpty(Object value, boolean trim) {
		if (value == null) return true;
		String text = value instanceof String ? (String) value : value.toString();
		return (trim ? text.trim() : text).isEmpty();
	}
	public static boolean notEmpty(Object value, boolean trim) {
		return !isEmpty(value, trim);
	}
	/** 不执行trim */
	public static boolean isEmpty(Object value) {
		return value == null || (value instanceof String ? (String) value : value.toString()).isEmpty();
	}
	/** 不执行trim */
	public static boolean notEmpty(Object value) {
		return !isEmpty(value);
	}
	public static String trim(String value) {
		return value == null ? null : value.trim();
	}

	public static String toString(Object value) {
		return value == null ? null : value.toString();
	}
	public static String toString(Object value, Object defaultValue) {
		return value == null ? toString(defaultValue) : value.toString();
	}
	public static String toString(Collection<?> collection, int maxLen) {
		if (collection == null) return null;
		
		StringBuilder buf = new StringBuilder(12 * maxLen);
		buf.append("[");
		int i = 0;
		for (Iterator<?> iterator = collection.iterator(); iterator.hasNext() && i < maxLen; i++) {
			buf.append(iterator.next()).append(", ");
		}
		if (buf.length() > 1) buf.deleteCharAt(buf.length() - 1);
		buf.append("]");
		return buf.toString();
	}
	
	
	public static String substring(String text, int beginIndex, int endIndex) {
		if (text == null) return null;
		if (beginIndex < 0) beginIndex = 0;
		if (beginIndex > text.length() - 1) return "";
		if (endIndex > text.length()) endIndex = text.length();
		return text.substring(beginIndex, endIndex);
	}
	
	
	public static String encodeURL(Object value) {
		if (value == null) return "";
		try {
			return URLEncoder.encode(value.toString(), "UTF-8");
		} catch (UnsupportedEncodingException e) {
			throw new IllegalStateException(e);
		}
	}
	public static String decodeURL(Object value) {
		if (value == null) return null;
		try {
			return URLDecoder.decode(value.toString(), "UTF-8");
		} catch (UnsupportedEncodingException e) {
			throw new IllegalStateException(e);
		}
	}
	
	
	private static final Character[] randomChars;
	private static final Character[] randomNumbers;
	static {
		{
			List<Character> chars = new ArrayList<>();
			addChars(chars, 'a', 'z');
			addChars(chars, 'A', 'Z');
			addChars(chars, '0', '9');
			Collections.shuffle(chars, random);
			randomChars = chars.toArray(new Character[0]);
		}
		{
			List<Character> chars = new ArrayList<>();
			addChars(chars, '0', '9');
			Collections.shuffle(chars, random);
			randomNumbers = chars.toArray(new Character[0]);
		}
	}
	private static void addChars(List<Character> list, int start, int end) {
		for (int i = start; i <= end; i++) {
			list.add((char) i);
		}
	}
	/** 生成数字随机码 */
	private static String randChars(Character[] chars, int len) {
		StringBuilder buf = new StringBuilder(len);
		for (int i = 0; i < len; i++) {
			buf.append(chars[random.nextInt(chars.length)]);
		}
		return buf.toString();
	}
	/** 生成字母数字随机码 */
	public static String randCode(int len) {
		return randChars(randomChars, len);
	}
	/** 生成数字随机码 */
	public static String randNumCode(int len) {
		return randChars(randomNumbers, len);
	}
	
	/** 集合中的元素连接起来(不忽略空元素) */
	public static String concat(Collection<?> collection, String split) {
		return concat(collection, split, false);
	}
	
	/** 集合中的元素连接起来 */
	public static String concat(Collection<?> collection, String split, boolean ignoreNullEl) {
		if (collection == null || collection.isEmpty()) return "";
		
		if (split == null) split = "";
		StringBuilder buf = new StringBuilder(collection.size() * (10 + split.length()));
		for (Object el : collection) {
			if (ignoreNullEl && el == null) continue;
			
			buf.append(el).append(split);
		}
		if (buf.length() > 0) buf.setLength(buf.length() - split.length());
		return buf.toString();
	}
	
	/** 集合中的元素连接起来(不忽略空元素) */
	public static <T> String concat(T[] array, String split) {
		return concat(array, split, false);
	}
	
	/** 集合中的元素连接起来 */
	public static <T> String concat(T[] array, String split, boolean ignoreNullEl) {
		if (array == null || array.length == 0) return "";
		
		if (split == null) split = "";
		StringBuilder buf = new StringBuilder(array.length * (10 + split.length()));
		for (Object el : array) {
			if (ignoreNullEl && el == null) continue;
			
			buf.append(el).append(split);
		}
		if (buf.length() > 0) buf.setLength(buf.length() - split.length());
		return buf.toString();
	}

	
	/**
     * 切分后自动执行trim
     * @see #split(String, char, boolean, Integer)
     */
   	public static List<String> split(String text, final char splitChar) {
   		return split(text, splitChar, true, text.length() / 16);
   	}
    /**
	 * 非正则表达式方式split，大量计算时可以节省cpu<br>
	 * 如果做缓存时，注意String的特性——共享一个char数组，潜在的jvm内存泄漏 
	 * @param text	原始文本
	 * @param splitChar 分割字符
	 * @param initialCapacity 初始化List容量大小
	 * @return 切分后字符串
	 */
	public static List<String> split(String text, final char splitChar, boolean trim, Integer initialCapacity) {
		List<String> result = (initialCapacity == null || initialCapacity < 10) ? new ArrayList<String>()
				: new ArrayList<String>(initialCapacity);
		int start = 0, len = text.length();
		for (int i = 0; i < len; i++) {
			if (splitChar == text.charAt(i)) {
				String tmp = start == i ? "" : text.substring(start, i);
				result.add(trim ? tmp.trim() : tmp);
				start = i + 1;
			}
		}
		if (start <= len) {
			String tmp = text.substring(start);
			result.add(trim ? tmp.trim() : tmp);
		}
		return result;
	}
	/** 是否是整数 */
	public static boolean isNumber(String text) {
		if (text == null) return false;
		
		for (int i = 0, len = text.length(); i < len; i++) {
			char ch = text.charAt(i);
			if (ch > '9' || ch < '0') return false;
		}
		return true;
	}
	
	/** @see #fillZero(String, int) */
	public static String format(int value, int len) {
		return fillZero(Integer.toString(value), len);
	}
	
	/**
	 * 字符填充0
	 * @param str 字符串
	 * @param maxLen 补零后最大长度
	 * @return String 返回补零后的字符串
	 */
	public static String fillZero(String str,int maxLen){
		if (str == null) str = "";
		if (str.length() >= maxLen) return str;
		
		StringBuilder buf = new StringBuilder();
		for (int i = str.length(); i < maxLen; i++) {
			buf.append('0');
		}
		buf.append(str);
		return buf.toString();
	}
	
	public static String base64Encode(String text) {
		return text == null ? null : Base64.getEncoder().encodeToString(text.getBytes(UtilIo.utf8));
	}
	public static byte[] base64Decode(String src) {
		return src == null ? null : Base64.getDecoder().decode(src);
	}
	public static String base64UrlEncode(String text) {
		return text == null ? null : Base64.getUrlEncoder().encodeToString(text.getBytes(UtilIo.utf8));
	}
	public static byte[] base64UrlDecode(String src) {
		return src == null ? null : Base64.getUrlDecoder().decode(src);
	}
	public static String base64MimeEncode(String text) {
		return text == null ? null : Base64.getMimeEncoder().encodeToString(text.getBytes(UtilIo.utf8));
	}
	public static byte[] base64MimeDecode(String src) {
		return src == null ? null : Base64.getMimeDecoder().decode(src);
	}
	
	/**
	 * @see org.springframework.util.StringUtils#tokenizeToStringArray(String, String, boolean, boolean)
	 */
	public static String[] tokenizeToStringArray(String str, String delimiters, boolean trimTokens, boolean ignoreEmptyTokens) {
		if (str == null) return null;

		StringTokenizer st = new StringTokenizer(str, delimiters);
		List<String> tokens = new ArrayList<String>();
		while (st.hasMoreTokens()) {
			String token = st.nextToken();
			if (trimTokens) token = token.trim();
			
			if (!ignoreEmptyTokens || token.length() > 0) tokens.add(token);
		}
		return tokens.toArray(new String[tokens.size()]);
	}
	
	/**
	 * 将驼峰式命名的字符串转换为下划线大写方式。如果转换前的驼峰式命名的字符串为空，则返回空字符串。</br>
	 * 例如：HelloWorld->HELLO_WORLD
	 * @param name 转换前的驼峰式命名的字符串
	 * @return 转换后下划线大写方式命名的字符串
	 */
	public static String camelToUnderLineName(String camelName) {
	    StringBuilder result = new StringBuilder();
	    if (camelName != null && camelName.length() > 0) {
	        // 将第一个字符处理成大写
	        result.append(camelName.substring(0, 1).toUpperCase());
	        // 循环处理其余字符
	        for (int i = 1; i < camelName.length(); i++) {
	            String s = camelName.substring(i, i + 1);
	            // 在大写字母前添加下划线
	            if (s.equals(s.toUpperCase()) && !Character.isDigit(s.charAt(0)) && !".".equals(s)) {
	                result.append("_");
	            }
	            // 其他字符直接转成大写
	            result.append(s.toUpperCase());
	        }
	    }
	    return result.toString();
	}
	public  static Double getAcceleration(Double d){
		Double result=0.0d;
		if(d<1&&d>0){
			result=1.3d;
		}else if(d>1&&d<=2){
			result=1.2d;
		}else if(d>2&&d<=8){
			result=1.0d;
		}else{
			result=1.0d;
		}
		return result;
	}
	
}
